Overall Objective

Load Libraries

library(tidyverse)
library(cowplot)
library(broom)
library(plotly)

Import data

Convert data from ‘wide’ to ‘long’ format

# data
data1 <- data %>%
  gather(Sample,Count,2:49)
# Separate samples by identifiers 
data2 <- data1 %>% 
  separate(Sample, into=c("Sample_ID","Dilution_factor",
                          "Injection","Tech_rep", sep = "_")) %>% 
  select(-`_`)
# Standards
standards1 <- standards %>% 
  gather(Sample,Count,2:25)
standards2 <- standards1 %>% 
  separate(Sample, into=c("Sample_ID","When","Dilution_factor",
                          "Nano_day","Injection","Tech_Rep", sep = "_")) %>% 
  select(-`_`)

Factor the data into categorical variables

# Refactoring Columns for samples
data2$Sample_ID <- as.factor(data2$Sample_ID)
data2$Dilution_factor <- as.numeric(data2$Dilution_factor)
data2$Injection<- as.factor(data2$Injection)
data2$Tech_rep <- as.numeric(data2$Tech_rep)
data2
# Refactoring COlumns for key
key$Sample_ID <- as.factor(key$Sample_ID)
key$Time <- as.factor(key$Time)
key$Treatment <- as.factor(key$Treatment)
key$Volume <- as.numeric(key$Volume)
key$Treatment <- factor(key$Treatment,levels = c('DMSO','EGF','BPS','BPS_EGF'))
key
# Refactoring columns for standards
standards2$Sample_ID <- as.factor(standards2$Sample_ID)
standards2$When <- as.factor(standards2$When)
standards2$Dilution_factor <- as.numeric(standards2$Dilution_factor)
standards2$Injection <- as.factor(standards2$Injection)
standards2$Nano_day <- as.numeric(standards2$Nano_day)
standards2

Back calculate standards

standards2 <- standards2 %>% 
  mutate(True_Count=Dilution_factor*Count)
# Set the correct order of 'categorical factors'
standards2$Nano_day <-  factor(standards2$Nano_day, levels=c('1','2'))
standards2$When <- factor(standards2$When, levels=c('before','after'))
standards2

Summarize three technical standard replicates

standards3 <- standards2 %>% 
  group_by(particle_size,Sample_ID,When,Dilution_factor,Nano_day,Injection) %>% 
  summarise( tech_N = length(True_Count),
             tech_mean = mean(True_Count),
             tech_sd = sd(True_Count),
             tech_se = tech_sd/sqrt(tech_N))
standards3

Summarize standards by injection

standards4 <- standards3 %>% 
  group_by(Nano_day,When,particle_size) %>% 
  summarise( inj_N = length(tech_mean),
             inj_mean = mean(tech_mean),
             inj_sd = sd(tech_mean),
             inj_se = inj_sd/sqrt(inj_N))
standards4

Plot before and after plots, facet by experimental day

std_plot <- standards4 %>% 
  ggplot(aes(x = particle_size, y = inj_mean, color=When))+
  geom_line(size=2) + xlim(0,300)+ #line size, x-axis scale
  geom_ribbon(aes(ymin=inj_mean-inj_se, ymax=inj_mean+inj_se),
              alpha=0.4,fill = alpha('grey12', 0.2)) + #error bars
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration/ml\n") + # Y axis label
  ggtitle("Nanosight Histogram of\n100nm Standards")+ #title
  labs(color="Condition")+ #Label table title
  facet_wrap(~ Nano_day)
std_plot

# ggsave("Standards_histogram_plot.png",
#        height = 5, width = 7, dpi = 300, units= "in")

Standards particle concentrations from each experimental day

standards_df <- standards4 %>% 
  group_by(Nano_day,When) %>% 
  summarise(total=sum(inj_mean))
standards_df

Bar graph of standards particle concentrations

standards_bar <- standards_df %>% 
  ggplot(aes(x=Nano_day,y=total,fill=When))+
  geom_col(position="dodge")+
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Experimental Day") + # X axis label
  ylab("\nMean Particle Concentration/ml\n") + # Y axis label
  ggtitle("Nanosight Histogram of\n100nm Standards")+ #title
  labs(color="When") #Label table title
standards_bar

# ggsave("Standards_bar_plot.png",
#        height = 5, width = 7, dpi = 300, units= "in")

Intraassay variability

Intra.assay_cv <- standards_df %>% 
  group_by(Nano_day) %>% 
  summarise(Intra_Day_N = length(total),
            Intra_Day_mean = mean(total),
            Intra_Day_sd = sd(total),
            Intra_Day_se = Intra_Day_sd/sqrt(Intra_Day_N),
            Intra_Day_cv = Intra_Day_sd/Intra_Day_mean )
Intra.assay_cv
# # Save as .csv
# write_csv(Intra.assay_cv,"Intra.assay_cv.csv")

Interassay variability

Inter.assay_cv <- Intra.assay_cv %>% 
  summarise(Inter_Day_N = length(Intra_Day_mean),
            Inter_Day_mean = mean(Intra_Day_mean),
            Inter_Day_sd = sd(Intra_Day_mean),
            Inter_Day_se = Inter_Day_sd/sqrt(Inter_Day_N),
            Inter_Day_cv = Inter_Day_sd/Inter_Day_mean )
Inter.assay_cv
# # Save as .csv
# write_csv(Inter.assay_cv,"Inter.assay_cv.csv")

Sample analysis

Back calculate the original concentration of the sample

data2 <- data2 %>% 
  mutate(True_Count = Dilution_factor*Count)
data2

Average three technical readings

data3 <- data2 %>% 
  group_by(particle_size,Sample_ID,Dilution_factor,Injection) %>% 
  summarise( tech_N = length(True_Count),
             tech_mean = mean(True_Count),
             tech_sd = sd(True_Count),
             tech_se = tech_sd/sqrt(tech_N))
data3

Summarize samples by injection (average both injections)

data4 <- data3 %>% 
  group_by(particle_size,Sample_ID,Dilution_factor) %>% 
  summarise( inj_N = length(tech_mean),
             inj_mean = mean(tech_mean),
             inj_sd = sd(tech_mean),
             inj_se = inj_sd/sqrt(inj_N))
data4
# Average technical replicates and merge with key
merge <- left_join(key,data3, by= "Sample_ID")
merge
# Save as .csv
# write_csv(merge,"Technical_replicate_average.csv")
 
# Average injection replicates and merge with key
merge1 <- left_join(key,data4, by= "Sample_ID")
merge1
# #Save as .csv
# write_csv(merge1,"Injection_replicate_average.csv")

Quick visualizations

Graphing all samples

sample_plot <- merge %>%
  ggplot(aes(x=particle_size, y=tech_mean,color=Injection ))+ #plot
  geom_ribbon(aes(ymin=tech_mean-tech_se,
                  ymax=tech_mean+tech_se),
                  alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=2.0, alpha = 0.8) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration/ml\n") + # Y axis label
  ggtitle("Nanosight Histogram of\nhCTBS treated with BPS")+ #title
  labs(color="Injection")+ #Label table title
  facet_grid(Time ~ Treatment)
  # geom_vline(xintercept = 200)+
  # annotate("text", x= 350, y = 1E8, label= "200nm")
sample_plot

# ggsave("Nanosight_Sample_Histogram.png", plot = sample_plot,
#        height = 10, width = 14, dpi = 200, units= "in")

Interactive Plot

ggplotly(sample_plot)

Particle concentration values for each of the samples

merge2 <- merge1 %>% 
  group_by(Time, Treatment, Volume) %>% 
  summarise(particle_conc=sum(inj_mean))
merge2

Correct for resuspension volume

merge3 <- merge2 %>% 
  mutate(particle_count = (Volume/1000)*particle_conc, # Create new column with number of particles
         corrected_particle_conc = (particle_conc/1E9)) # Create new column with correct particle concentration
merge3
# Save as .csv
# write_csv(merge3,"Adjusted_particle_concentration.csv")

Barplot

plot1 <- merge3 %>% 
  ggplot(aes(x = Treatment, y = corrected_particle_conc, fill = Treatment)) +
  geom_bar(aes(text = paste("Particle Concentration:",
                            corrected_particle_conc)),
           stat="identity", position = "dodge")+
  xlab("\nTreatment\n") + # X axis label
  ylab("\nMean Vessicle Concentration\n(10^9 particles/ ml)\n") + # Y axis label
  ggtitle("Effect of BPS on Extracellular Vessicle\nRelease of hCTBs\n")+
  scale_y_continuous(breaks = seq(0,14,2),
                     limits = c(0,14),
                     expand = c(0,0))+ # set bottom of graph
  labs(color="Condition")+ # Label table title
  facet_wrap(~Time)
Ignoring unknown aesthetics: text
  
plot1

# ggsave("BPS_treated_hCTBs_48_96_facet_plot.png",
#       height = 8, width = 10, dpi = 600, units= "in")

Interactive Plot

ggplotly(plot1)

Barplot

plot2 <- merge3 %>%
  group_by(Time) %>% 
  ggplot(aes(x = Treatment, y = corrected_particle_conc, fill = Time )) +
  geom_bar(position = "dodge", stat = "identity")+
  xlab("\nTreatment\n") + # X axis label
  ylab("\nMean Vessicle Concentration\n(10^9 particles/ ml)\n") + # Y axis label
  ggtitle("Effect of BPS on Extracellular Vessicle\nRelease of hCTBs\n")+
  scale_y_continuous(breaks = seq(0,14,2),
                     limits = c(0,14),
                     expand = c(0,0))+ # set bottom of graph
  labs(fill= "Time (hr)")
plot2

 # ggsave("BPS_treated_hCTBs_48_96_plot.png",
 #       height = 5, width = 7, dpi = 600, units= "in")

Interactive Plot

ggplotly(plot2)

Statistics

fit <- aov(corrected_particle_conc ~ Time * Treatment ,data=merge3)
tidy(fit)
LS0tCnRpdGxlOiAiSHVtYW4gQ1RCIEJQUyBQcm9qZWN0IgphdXRob3I6ICJTZWFuIE5ndXllbiIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6IAogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0aGVtZTogZmxhdGx5CiAgaHRtbF9ub3RlYm9vazoKICAgIGRmX3ByaW50OiBwYWdlZAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAotLS0KI092ZXJhbGwgT2JqZWN0aXZlIAoKCiMjTG9hZCBMaWJyYXJpZXMKCmBgYHtyLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoYnJvb20pCmxpYnJhcnkocGxvdGx5KQoKYGBgCgojI0ltcG9ydCBkYXRhCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojc2V0d2QoIn4vR2l0SHViL0V4cGVyaW1lbnRzL0NUQl9CUFMvZGF0YS8iKQpzZXR3ZCgifi9MaWJyYXJ5L01vYmlsZSBEb2N1bWVudHMvY29tfmFwcGxlfkNsb3VkRG9jcy9FeHBlcmltZW50cy9DVEJfQlBTL2RhdGEvIikKCgpyYXdfZGF0YSA8LSAiQ1RCX3BpbG90XzQ4aHJfOTZoci1FeHBlcmltZW50U3VtbWFyeS5jc3YiCmtleV9kYXRhIDwtICJLZXlfaENUQlBldHJvZmZfTG9wZXouY3N2IgpzdGFuZGFyZF9kYXRhIDwtICJzdGRfQ1RCX3BpbG90XzQ4aHJfOTZoci1FeHBlcmltZW50U3VtbWFyeS5jc3YiCgoKZGF0YSA8LSByZWFkX2NzdihyYXdfZGF0YSkKc3RhbmRhcmRzIDwtIHJlYWRfY3N2KHN0YW5kYXJkX2RhdGEpCmtleSA8LSByZWFkX2NzdihrZXlfZGF0YSkKCmRhdGEKc3RhbmRhcmRzCmtleQpgYGAKCiMjQ29udmVydCBkYXRhIGZyb20gJ3dpZGUnIHRvICdsb25nJyBmb3JtYXQKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgZGF0YQpkYXRhMSA8LSBkYXRhICU+JQogIGdhdGhlcihTYW1wbGUsQ291bnQsMjo0OSkKCiMgU2VwYXJhdGUgc2FtcGxlcyBieSBpZGVudGlmaWVycyAKZGF0YTIgPC0gZGF0YTEgJT4lIAogIHNlcGFyYXRlKFNhbXBsZSwgaW50bz1jKCJTYW1wbGVfSUQiLCJEaWx1dGlvbl9mYWN0b3IiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJJbmplY3Rpb24iLCJUZWNoX3JlcCIsIHNlcCA9ICJfIikpICU+JSAKICBzZWxlY3QoLWBfYCkKCiMgU3RhbmRhcmRzCnN0YW5kYXJkczEgPC0gc3RhbmRhcmRzICU+JSAKICBnYXRoZXIoU2FtcGxlLENvdW50LDI6MjUpCgoKc3RhbmRhcmRzMiA8LSBzdGFuZGFyZHMxICU+JSAKICBzZXBhcmF0ZShTYW1wbGUsIGludG89YygiU2FtcGxlX0lEIiwiV2hlbiIsIkRpbHV0aW9uX2ZhY3RvciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIk5hbm9fZGF5IiwiSW5qZWN0aW9uIiwiVGVjaF9SZXAiLCBzZXAgPSAiXyIpKSAlPiUgCiAgc2VsZWN0KC1gX2ApCgoKYGBgCgoKIyNGYWN0b3IgdGhlIGRhdGEgaW50byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMKYGBge3IsIHdhcm5pbmc9RkFMU0V9CiMgUmVmYWN0b3JpbmcgQ29sdW1ucyBmb3Igc2FtcGxlcwpkYXRhMiRTYW1wbGVfSUQgPC0gYXMuZmFjdG9yKGRhdGEyJFNhbXBsZV9JRCkKZGF0YTIkRGlsdXRpb25fZmFjdG9yIDwtIGFzLm51bWVyaWMoZGF0YTIkRGlsdXRpb25fZmFjdG9yKQpkYXRhMiRJbmplY3Rpb248LSBhcy5mYWN0b3IoZGF0YTIkSW5qZWN0aW9uKQpkYXRhMiRUZWNoX3JlcCA8LSBhcy5udW1lcmljKGRhdGEyJFRlY2hfcmVwKQoKZGF0YTIKCiMgUmVmYWN0b3JpbmcgQ09sdW1ucyBmb3Iga2V5CmtleSRTYW1wbGVfSUQgPC0gYXMuZmFjdG9yKGtleSRTYW1wbGVfSUQpCmtleSRUaW1lIDwtIGFzLmZhY3RvcihrZXkkVGltZSkKa2V5JFRyZWF0bWVudCA8LSBhcy5mYWN0b3Ioa2V5JFRyZWF0bWVudCkKa2V5JFZvbHVtZSA8LSBhcy5udW1lcmljKGtleSRWb2x1bWUpCgprZXkkVHJlYXRtZW50IDwtIGZhY3RvcihrZXkkVHJlYXRtZW50LGxldmVscyA9IGMoJ0RNU08nLCdFR0YnLCdCUFMnLCdCUFNfRUdGJykpCgprZXkKCiMgUmVmYWN0b3JpbmcgY29sdW1ucyBmb3Igc3RhbmRhcmRzCnN0YW5kYXJkczIkU2FtcGxlX0lEIDwtIGFzLmZhY3RvcihzdGFuZGFyZHMyJFNhbXBsZV9JRCkKc3RhbmRhcmRzMiRXaGVuIDwtIGFzLmZhY3RvcihzdGFuZGFyZHMyJFdoZW4pCnN0YW5kYXJkczIkRGlsdXRpb25fZmFjdG9yIDwtIGFzLm51bWVyaWMoc3RhbmRhcmRzMiREaWx1dGlvbl9mYWN0b3IpCnN0YW5kYXJkczIkSW5qZWN0aW9uIDwtIGFzLmZhY3RvcihzdGFuZGFyZHMyJEluamVjdGlvbikKc3RhbmRhcmRzMiROYW5vX2RheSA8LSBhcy5udW1lcmljKHN0YW5kYXJkczIkTmFub19kYXkpCgpzdGFuZGFyZHMyCgpgYGAKCgoKIyMjQmFjayBjYWxjdWxhdGUgc3RhbmRhcmRzCmBgYHtyfQpzdGFuZGFyZHMyIDwtIHN0YW5kYXJkczIgJT4lIAogIG11dGF0ZShUcnVlX0NvdW50PURpbHV0aW9uX2ZhY3RvcipDb3VudCkKCiMgU2V0IHRoZSBjb3JyZWN0IG9yZGVyIG9mICdjYXRlZ29yaWNhbCBmYWN0b3JzJwpzdGFuZGFyZHMyJE5hbm9fZGF5IDwtICBmYWN0b3Ioc3RhbmRhcmRzMiROYW5vX2RheSwgbGV2ZWxzPWMoJzEnLCcyJykpCnN0YW5kYXJkczIkV2hlbiA8LSBmYWN0b3Ioc3RhbmRhcmRzMiRXaGVuLCBsZXZlbHM9YygnYmVmb3JlJywnYWZ0ZXInKSkKCnN0YW5kYXJkczIKYGBgCgojIyNTdW1tYXJpemUgdGhyZWUgdGVjaG5pY2FsIHN0YW5kYXJkIHJlcGxpY2F0ZXMKYGBge3J9CnN0YW5kYXJkczMgPC0gc3RhbmRhcmRzMiAlPiUgCiAgZ3JvdXBfYnkocGFydGljbGVfc2l6ZSxTYW1wbGVfSUQsV2hlbixEaWx1dGlvbl9mYWN0b3IsTmFub19kYXksSW5qZWN0aW9uKSAlPiUgCiAgc3VtbWFyaXNlKCB0ZWNoX04gPSBsZW5ndGgoVHJ1ZV9Db3VudCksCiAgICAgICAgICAgICB0ZWNoX21lYW4gPSBtZWFuKFRydWVfQ291bnQpLAogICAgICAgICAgICAgdGVjaF9zZCA9IHNkKFRydWVfQ291bnQpLAogICAgICAgICAgICAgdGVjaF9zZSA9IHRlY2hfc2Qvc3FydCh0ZWNoX04pKQpzdGFuZGFyZHMzCmBgYAoKCiMjI1N1bW1hcml6ZSBzdGFuZGFyZHMgYnkgaW5qZWN0aW9uCmBgYHtyfQpzdGFuZGFyZHM0IDwtIHN0YW5kYXJkczMgJT4lIAogIGdyb3VwX2J5KE5hbm9fZGF5LFdoZW4scGFydGljbGVfc2l6ZSkgJT4lIAogIHN1bW1hcmlzZSggaW5qX04gPSBsZW5ndGgodGVjaF9tZWFuKSwKICAgICAgICAgICAgIGlual9tZWFuID0gbWVhbih0ZWNoX21lYW4pLAogICAgICAgICAgICAgaW5qX3NkID0gc2QodGVjaF9tZWFuKSwKICAgICAgICAgICAgIGlual9zZSA9IGlual9zZC9zcXJ0KGlual9OKSkKc3RhbmRhcmRzNAoKYGBgCgojIyNQbG90IGJlZm9yZSBhbmQgYWZ0ZXIgcGxvdHMsIGZhY2V0IGJ5IGV4cGVyaW1lbnRhbCBkYXkKYGBge3J9CnN0ZF9wbG90IDwtIHN0YW5kYXJkczQgJT4lIAogIGdncGxvdChhZXMoeCA9IHBhcnRpY2xlX3NpemUsIHkgPSBpbmpfbWVhbiwgY29sb3I9V2hlbikpKwogIGdlb21fbGluZShzaXplPTIpICsgeGxpbSgwLDMwMCkrICNsaW5lIHNpemUsIHgtYXhpcyBzY2FsZQogIGdlb21fcmliYm9uKGFlcyh5bWluPWlual9tZWFuLWlual9zZSwgeW1heD1pbmpfbWVhbitpbmpfc2UpLAogICAgICAgICAgICAgIGFscGhhPTAuNCxmaWxsID0gYWxwaGEoJ2dyZXkxMicsIDAuMikpICsgI2Vycm9yIGJhcnMKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kPWMoMCwwKSkrICNzZXQgYm90dG9tIG9mIGdyYXBoCiAgeGxhYigiUGFydGljbGUgU2l6ZSIpICsgIyBYIGF4aXMgbGFiZWwKICB5bGFiKCJcbk1lYW4gUGFydGljbGUgQ29uY2VudHJhdGlvbi9tbFxuIikgKyAjIFkgYXhpcyBsYWJlbAogIGdndGl0bGUoIk5hbm9zaWdodCBIaXN0b2dyYW0gb2ZcbjEwMG5tIFN0YW5kYXJkcyIpKyAjdGl0bGUKICBsYWJzKGNvbG9yPSJDb25kaXRpb24iKSsgI0xhYmVsIHRhYmxlIHRpdGxlCiAgZmFjZXRfd3JhcCh+IE5hbm9fZGF5KQoKc3RkX3Bsb3QKCgojIGdnc2F2ZSgiU3RhbmRhcmRzX2hpc3RvZ3JhbV9wbG90LnBuZyIsCiMgICAgICAgIGhlaWdodCA9IDUsIHdpZHRoID0gNywgZHBpID0gMzAwLCB1bml0cz0gImluIikKYGBgCgojIyMgU3RhbmRhcmRzIHBhcnRpY2xlIGNvbmNlbnRyYXRpb25zIGZyb20gZWFjaCBleHBlcmltZW50YWwgZGF5CmBgYHtyfQpzdGFuZGFyZHNfZGYgPC0gc3RhbmRhcmRzNCAlPiUgCiAgZ3JvdXBfYnkoTmFub19kYXksV2hlbikgJT4lIAogIHN1bW1hcmlzZSh0b3RhbD1zdW0oaW5qX21lYW4pKQoKc3RhbmRhcmRzX2RmCmBgYAoKIyMjQmFyIGdyYXBoIG9mIHN0YW5kYXJkcyBwYXJ0aWNsZSBjb25jZW50cmF0aW9ucwpgYGB7cn0Kc3RhbmRhcmRzX2JhciA8LSBzdGFuZGFyZHNfZGYgJT4lIAogIGdncGxvdChhZXMoeD1OYW5vX2RheSx5PXRvdGFsLGZpbGw9V2hlbikpKwogIGdlb21fY29sKHBvc2l0aW9uPSJkb2RnZSIpKwogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9YygwLDApKSsgI3NldCBib3R0b20gb2YgZ3JhcGgKICB4bGFiKCJFeHBlcmltZW50YWwgRGF5IikgKyAjIFggYXhpcyBsYWJlbAogIHlsYWIoIlxuTWVhbiBQYXJ0aWNsZSBDb25jZW50cmF0aW9uL21sXG4iKSArICMgWSBheGlzIGxhYmVsCiAgZ2d0aXRsZSgiTmFub3NpZ2h0IEhpc3RvZ3JhbSBvZlxuMTAwbm0gU3RhbmRhcmRzIikrICN0aXRsZQogIGxhYnMoY29sb3I9IldoZW4iKSAjTGFiZWwgdGFibGUgdGl0bGUKCnN0YW5kYXJkc19iYXIKCiMgZ2dzYXZlKCJTdGFuZGFyZHNfYmFyX3Bsb3QucG5nIiwKIyAgICAgICAgaGVpZ2h0ID0gNSwgd2lkdGggPSA3LCBkcGkgPSAzMDAsIHVuaXRzPSAiaW4iKQpgYGAKCiMjI0ludHJhYXNzYXkgdmFyaWFiaWxpdHkKYGBge3J9CkludHJhLmFzc2F5X2N2IDwtIHN0YW5kYXJkc19kZiAlPiUgCiAgZ3JvdXBfYnkoTmFub19kYXkpICU+JSAKICBzdW1tYXJpc2UoSW50cmFfRGF5X04gPSBsZW5ndGgodG90YWwpLAogICAgICAgICAgICBJbnRyYV9EYXlfbWVhbiA9IG1lYW4odG90YWwpLAogICAgICAgICAgICBJbnRyYV9EYXlfc2QgPSBzZCh0b3RhbCksCiAgICAgICAgICAgIEludHJhX0RheV9zZSA9IEludHJhX0RheV9zZC9zcXJ0KEludHJhX0RheV9OKSwKICAgICAgICAgICAgSW50cmFfRGF5X2N2ID0gSW50cmFfRGF5X3NkL0ludHJhX0RheV9tZWFuICkKSW50cmEuYXNzYXlfY3YKCiMgIyBTYXZlIGFzIC5jc3YKIyB3cml0ZV9jc3YoSW50cmEuYXNzYXlfY3YsIkludHJhLmFzc2F5X2N2LmNzdiIpCmBgYAoKIyMjSW50ZXJhc3NheSB2YXJpYWJpbGl0eQpgYGB7cn0KSW50ZXIuYXNzYXlfY3YgPC0gSW50cmEuYXNzYXlfY3YgJT4lIAogIHN1bW1hcmlzZShJbnRlcl9EYXlfTiA9IGxlbmd0aChJbnRyYV9EYXlfbWVhbiksCiAgICAgICAgICAgIEludGVyX0RheV9tZWFuID0gbWVhbihJbnRyYV9EYXlfbWVhbiksCiAgICAgICAgICAgIEludGVyX0RheV9zZCA9IHNkKEludHJhX0RheV9tZWFuKSwKICAgICAgICAgICAgSW50ZXJfRGF5X3NlID0gSW50ZXJfRGF5X3NkL3NxcnQoSW50ZXJfRGF5X04pLAogICAgICAgICAgICBJbnRlcl9EYXlfY3YgPSBJbnRlcl9EYXlfc2QvSW50ZXJfRGF5X21lYW4gKQpJbnRlci5hc3NheV9jdgoKIyAjIFNhdmUgYXMgLmNzdgojIHdyaXRlX2NzdihJbnRlci5hc3NheV9jdiwiSW50ZXIuYXNzYXlfY3YuY3N2IikKYGBgCgoKCiNTYW1wbGUgYW5hbHlzaXMKCiMjI0JhY2sgY2FsY3VsYXRlIHRoZSBvcmlnaW5hbCBjb25jZW50cmF0aW9uIG9mIHRoZSBzYW1wbGUKYGBge3J9CmRhdGEyIDwtIGRhdGEyICU+JSAKICBtdXRhdGUoVHJ1ZV9Db3VudCA9IERpbHV0aW9uX2ZhY3RvcipDb3VudCkKZGF0YTIKYGBgCgoKIyMjIEF2ZXJhZ2UgdGhyZWUgdGVjaG5pY2FsIHJlYWRpbmdzCmBgYHtyfQpkYXRhMyA8LSBkYXRhMiAlPiUgCiAgZ3JvdXBfYnkocGFydGljbGVfc2l6ZSxTYW1wbGVfSUQsRGlsdXRpb25fZmFjdG9yLEluamVjdGlvbikgJT4lIAogIHN1bW1hcmlzZSggdGVjaF9OID0gbGVuZ3RoKFRydWVfQ291bnQpLAogICAgICAgICAgICAgdGVjaF9tZWFuID0gbWVhbihUcnVlX0NvdW50KSwKICAgICAgICAgICAgIHRlY2hfc2QgPSBzZChUcnVlX0NvdW50KSwKICAgICAgICAgICAgIHRlY2hfc2UgPSB0ZWNoX3NkL3NxcnQodGVjaF9OKSkKZGF0YTMKYGBgCgojI1N1bW1hcml6ZSBzYW1wbGVzIGJ5IGluamVjdGlvbiAoYXZlcmFnZSBib3RoIGluamVjdGlvbnMpCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQoKZGF0YTQgPC0gZGF0YTMgJT4lIAogIGdyb3VwX2J5KHBhcnRpY2xlX3NpemUsU2FtcGxlX0lELERpbHV0aW9uX2ZhY3RvcikgJT4lIAogIHN1bW1hcmlzZSggaW5qX04gPSBsZW5ndGgodGVjaF9tZWFuKSwKICAgICAgICAgICAgIGlual9tZWFuID0gbWVhbih0ZWNoX21lYW4pLAogICAgICAgICAgICAgaW5qX3NkID0gc2QodGVjaF9tZWFuKSwKICAgICAgICAgICAgIGlual9zZSA9IGlual9zZC9zcXJ0KGlual9OKSkKZGF0YTQKCiMgQXZlcmFnZSB0ZWNobmljYWwgcmVwbGljYXRlcyBhbmQgbWVyZ2Ugd2l0aCBrZXkKbWVyZ2UgPC0gbGVmdF9qb2luKGtleSxkYXRhMywgYnk9ICJTYW1wbGVfSUQiKQoKbWVyZ2UKCiMgU2F2ZSBhcyAuY3N2CiMgd3JpdGVfY3N2KG1lcmdlLCJUZWNobmljYWxfcmVwbGljYXRlX2F2ZXJhZ2UuY3N2IikKIAojIEF2ZXJhZ2UgaW5qZWN0aW9uIHJlcGxpY2F0ZXMgYW5kIG1lcmdlIHdpdGgga2V5Cm1lcmdlMSA8LSBsZWZ0X2pvaW4oa2V5LGRhdGE0LCBieT0gIlNhbXBsZV9JRCIpCgptZXJnZTEKCiMgI1NhdmUgYXMgLmNzdgojIHdyaXRlX2NzdihtZXJnZTEsIkluamVjdGlvbl9yZXBsaWNhdGVfYXZlcmFnZS5jc3YiKQoKYGBgCgoKCiNRdWljayB2aXN1YWxpemF0aW9ucwoKIyMjIEdyYXBoaW5nIGFsbCBzYW1wbGVzCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQpzYW1wbGVfcGxvdCA8LSBtZXJnZSAlPiUKICBnZ3Bsb3QoYWVzKHg9cGFydGljbGVfc2l6ZSwgeT10ZWNoX21lYW4sY29sb3I9SW5qZWN0aW9uICkpKyAjcGxvdAogIGdlb21fcmliYm9uKGFlcyh5bWluPXRlY2hfbWVhbi10ZWNoX3NlLAogICAgICAgICAgICAgICAgICB5bWF4PXRlY2hfbWVhbit0ZWNoX3NlKSwKICAgICAgICAgICAgICAgICAgYWxwaGE9MC4yLGZpbGwgPSBhbHBoYSgnZ3JleTEyJywgMC4yKSkgKyAjZXJyb3IgYmFycwogIGdlb21fbGluZShzaXplPTIuMCwgYWxwaGEgPSAwLjgpICsgeGxpbSgwLDUwMCkrICNsaW5lIHNpemUsIHgtYXhpcyBzY2FsZQogIHNjYWxlX3lfY29udGludW91cyhleHBhbmQ9YygwLDApKSsgI3NldCBib3R0b20gb2YgZ3JhcGgKICB4bGFiKCJQYXJ0aWNsZSBTaXplIikgKyAjIFggYXhpcyBsYWJlbAogIHlsYWIoIlxuTWVhbiBQYXJ0aWNsZSBDb25jZW50cmF0aW9uL21sXG4iKSArICMgWSBheGlzIGxhYmVsCiAgZ2d0aXRsZSgiTmFub3NpZ2h0IEhpc3RvZ3JhbSBvZlxuaENUQlMgdHJlYXRlZCB3aXRoIEJQUyIpKyAjdGl0bGUKICBsYWJzKGNvbG9yPSJJbmplY3Rpb24iKSsgI0xhYmVsIHRhYmxlIHRpdGxlCiAgZmFjZXRfZ3JpZChUaW1lIH4gVHJlYXRtZW50KQogICMgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMjAwKSsKICAjIGFubm90YXRlKCJ0ZXh0IiwgeD0gMzUwLCB5ID0gMUU4LCBsYWJlbD0gIjIwMG5tIikKCnNhbXBsZV9wbG90CgojIGdnc2F2ZSgiTmFub3NpZ2h0X1NhbXBsZV9IaXN0b2dyYW0ucG5nIiwgcGxvdCA9IHNhbXBsZV9wbG90LAojICAgICAgICBoZWlnaHQgPSAxMCwgd2lkdGggPSAxNCwgZHBpID0gMjAwLCB1bml0cz0gImluIikKYGBgCiMjI0ludGVyYWN0aXZlIFBsb3QKYGBge3J9CmdncGxvdGx5KHNhbXBsZV9wbG90KQpgYGAKCgoKIyMjIFBhcnRpY2xlIGNvbmNlbnRyYXRpb24gdmFsdWVzIGZvciBlYWNoIG9mIHRoZSBzYW1wbGVzCmBgYHtyfQptZXJnZTIgPC0gbWVyZ2UxICU+JSAKICBncm91cF9ieShUaW1lLCBUcmVhdG1lbnQsIFZvbHVtZSkgJT4lIAogIHN1bW1hcmlzZShwYXJ0aWNsZV9jb25jPXN1bShpbmpfbWVhbikpCm1lcmdlMgpgYGAKCiMjIyBDb3JyZWN0IGZvciByZXN1c3BlbnNpb24gdm9sdW1lCmBgYHtyfQptZXJnZTMgPC0gbWVyZ2UyICU+JSAKICBtdXRhdGUocGFydGljbGVfY291bnQgPSAoVm9sdW1lLzEwMDApKnBhcnRpY2xlX2NvbmMsICMgQ3JlYXRlIG5ldyBjb2x1bW4gd2l0aCBudW1iZXIgb2YgcGFydGljbGVzCiAgICAgICAgIGNvcnJlY3RlZF9wYXJ0aWNsZV9jb25jID0gKHBhcnRpY2xlX2NvbmMvMUU5KSkgIyBDcmVhdGUgbmV3IGNvbHVtbiB3aXRoIGNvcnJlY3QgcGFydGljbGUgY29uY2VudHJhdGlvbgptZXJnZTMKCiMgU2F2ZSBhcyAuY3N2CiMgd3JpdGVfY3N2KG1lcmdlMywiQWRqdXN0ZWRfcGFydGljbGVfY29uY2VudHJhdGlvbi5jc3YiKQoKYGBgCgoKIyMjQmFycGxvdApgYGB7ciwgd2FybmluZz1UUlVFfQpwbG90MSA8LSBtZXJnZTMgJT4lIAogIGdncGxvdChhZXMoeCA9IFRyZWF0bWVudCwgeSA9IGNvcnJlY3RlZF9wYXJ0aWNsZV9jb25jLCBmaWxsID0gVHJlYXRtZW50KSkgKwogIGdlb21fYmFyKGFlcyh0ZXh0ID0gcGFzdGUoIlBhcnRpY2xlIENvbmNlbnRyYXRpb246IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlY3RlZF9wYXJ0aWNsZV9jb25jKSksCiAgICAgICAgICAgc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpKwogIHhsYWIoIlxuVHJlYXRtZW50XG4iKSArICMgWCBheGlzIGxhYmVsCiAgeWxhYigiXG5NZWFuIFZlc3NpY2xlIENvbmNlbnRyYXRpb25cbigxMF45IHBhcnRpY2xlcy8gbWwpXG4iKSArICMgWSBheGlzIGxhYmVsCiAgZ2d0aXRsZSgiRWZmZWN0IG9mIEJQUyBvbiBFeHRyYWNlbGx1bGFyIFZlc3NpY2xlXG5SZWxlYXNlIG9mIGhDVEJzXG4iKSsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsMTQsMiksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwxNCksCiAgICAgICAgICAgICAgICAgICAgIGV4cGFuZCA9IGMoMCwwKSkrICMgc2V0IGJvdHRvbSBvZiBncmFwaAogIGxhYnMoY29sb3I9IkNvbmRpdGlvbiIpKyAjIExhYmVsIHRhYmxlIHRpdGxlCiAgZmFjZXRfd3JhcCh+VGltZSkKCiAgCnBsb3QxCgojIGdnc2F2ZSgiQlBTX3RyZWF0ZWRfaENUQnNfNDhfOTZfZmFjZXRfcGxvdC5wbmciLAojICAgICAgIGhlaWdodCA9IDgsIHdpZHRoID0gMTAsIGRwaSA9IDYwMCwgdW5pdHM9ICJpbiIpCmBgYAojI0ludGVyYWN0aXZlIFBsb3QKYGBge3J9CmdncGxvdGx5KHBsb3QxKQpgYGAKCiMjI0JhcnBsb3QKYGBge3J9CnBsb3QyIDwtIG1lcmdlMyAlPiUKICBncm91cF9ieShUaW1lKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gY29ycmVjdGVkX3BhcnRpY2xlX2NvbmMsIGZpbGwgPSBUaW1lICkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSsKICB4bGFiKCJcblRyZWF0bWVudFxuIikgKyAjIFggYXhpcyBsYWJlbAogIHlsYWIoIlxuTWVhbiBWZXNzaWNsZSBDb25jZW50cmF0aW9uXG4oMTBeOSBwYXJ0aWNsZXMvIG1sKVxuIikgKyAjIFkgYXhpcyBsYWJlbAogIGdndGl0bGUoIkVmZmVjdCBvZiBCUFMgb24gRXh0cmFjZWxsdWxhciBWZXNzaWNsZVxuUmVsZWFzZSBvZiBoQ1RCc1xuIikrCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDE0LDIpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsMTQpLAogICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBjKDAsMCkpKyAjIHNldCBib3R0b20gb2YgZ3JhcGgKICBsYWJzKGZpbGw9ICJUaW1lIChocikiKQoKcGxvdDIKCiAjIGdnc2F2ZSgiQlBTX3RyZWF0ZWRfaENUQnNfNDhfOTZfcGxvdC5wbmciLAogIyAgICAgICBoZWlnaHQgPSA1LCB3aWR0aCA9IDcsIGRwaSA9IDYwMCwgdW5pdHM9ICJpbiIpCmBgYAojIyBJbnRlcmFjdGl2ZSBQbG90CmBgYHtyfQpnZ3Bsb3RseShwbG90MikKYGBgCgoKCiMgU3RhdGlzdGljcwoKYGBge3J9CmZpdCA8LSBhb3YoY29ycmVjdGVkX3BhcnRpY2xlX2NvbmMgfiBUaW1lICogVHJlYXRtZW50ICxkYXRhPW1lcmdlMykKCnRpZHkoZml0KQpgYGAKCg==